package spoon.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import spoon.core.domain.Game;
import spoon.core.exception.ConvertException;

@Service
@Qualifier("bet365FootballService")
public class Bet365FootballService extends Bet365AbstractService {

	@Value("#{bet365['football.url']}")
	private String GATE_URL;

	@Resource(name = "bet365.football.league")
	protected void getLeagueMap(Map<String, String> map) {
		this.leagueMap = map;
	}

	@Resource(name = "bet365.football.team")
	protected void getTeamMap(Map<String, String> map) {
		this.teamMap = map;
	}

	@Value("#{bet365['football.itemCode']}")
	protected void getItemCode(String itemCode) {
		this.ITEM_CODE = itemCode;
	}

	@Value("#{bet365['football.itemName']}")
	protected void getItemName(String itemName) {
		this.ITEM_NAME = itemName;
	}

	@Override
	public List<Game> getLeagueList() {
		log.info("===================================================================");
		log.info("    {} {} 리그 정보 검색 시작", SITE, ITEM_CODE);

		List<Game> leagueList = new ArrayList<Game>();
		String nation = null;
		boolean isValid = false;
		int leagueCnt = 0;

		String source = httpService.getSource(GATE_URL);
		StringTokenizer line = new StringTokenizer(source, "|");

		while (line.hasMoreElements()) {
			String token = line.nextToken();

			if (token.startsWith("MA")) {
				nation = getTokenValue(token, "NA");

				// 영국부터 시작한다.
				if (("United Kingdom").equals(nation)) {
					isValid = true;
				}

				if (("To Win Outright").equals(nation)) {
					isValid = false;
				}
			}

			if (isValid && token.startsWith("PA")) {
				Game league = new Game();
				league.setSite(SITE);
				league.setUrl(URL);
				league.setItemName(ITEM_NAME);
				league.setItemCode(ITEM_CODE);
				league.setNation(nation);
				league.setGameId(getTokenValue(token, "ID"));
				league.setLeagueName(getTokenValue(token, "NA"));
				league.setLink(getTokenValue(token, "PD"));
				leagueList.add(league);
				leagueCnt++;
			}
		}

		log.info("    {} {} 리그 정보 검색 종료. 전체 추가 리그수 = {}", SITE, ITEM_CODE, leagueCnt);
		log.info("===================================================================");

		return leagueList;
	}

	@Override
	@Async
	public void getGame(Game league) {
		long startTime = System.currentTimeMillis();

		int gameCnt = 0;
		int bettingCnt = 0;

		// 리그코드
		league.setLeagueCode(getLeagueCode(league.getLeagueName()));

		// 게임 상세정보에서 Full Time Result 를 가져온다.
		league.setLink(getLeagueLink(league.getLink()));

		// 리그별 게임 가져오기
		this.getGameList(league);

		// 데이터 입력
		bettingCnt = addBetting(league);
		gameCnt = league.getGameList().size();

		log.info("사이트: {}, 종목: {}, 국가: {}, 리그: {}, 경기수: {}, 베팅수: {}, 소요시간: {}초", SITE, ITEM_CODE, league.getNation(), league.getLeagueName(), gameCnt,
				bettingCnt, (System.currentTimeMillis() - startTime) / 1000.0f);
	}

	/**
	 * 리그안에 게임을 담는다.
	 * 
	 * @param league
	 */
	private void getGameList(Game league) {
		// 경기시간, 팀영, 승, 무, 패배당, 링크 구분자
		String source = httpService.getSource(convertLink(league.getLink()));
		String[] token = source.split("\\|CO");

		List<String> dateList = getTokenValues(token[1].substring(token[1].indexOf("PA")), "NA"); // 경기시간
		List<String> teamList = getTokenValues(token[2].substring(token[2].indexOf("PA")), "NA"); // 팀명
		List<String> homeList = getTokenValues(token[3].substring(token[3].indexOf("PA")), "NA"); // 승배당
		List<String> drawList = getTokenValues(token[4].substring(token[4].indexOf("PA")), "NA"); // 무배당
		List<String> awayList = getTokenValues(token[5].substring(token[5].indexOf("PA")), "NA"); // 패배당
		List<String> linkList = getTokenValues(token[6], "PD"); // 게임링크

		for (int i = 0; i < dateList.size(); i++) {
			Game game = new Game();

			// 날짜
			game.setGameDate(convertDate(dateList.get(i)));
			// 팀명
			String[] teams = teamList.get(i).split(" v ");
			if (teams.length != 2) {
				throw new ConvertException(new Throwable("팀명 변환 에러"));
			}

			game.setHomeTeamName(teams[0]);
			game.setHomeTeamCode(getTeamCode(teams[0]));
			game.setAwayTeamName(teams[1]);
			game.setAwayTeamCode(getTeamCode(teams[1]));

			// 승
			Game betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("1X2");
			betting.setBetName("Full Time Result");
			betting.setHandicap(0D);
			betting.setHandicapName("");
			betting.setBetRate(convertRate(homeList.get(i)));
			betting.setBetRateName(game.getHomeTeamCode());
			betting.setBetRateCode("1");
			game.addGameList(betting);

			// 무
			betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("1X2");
			betting.setBetName("Full Time Result");
			betting.setHandicap(0D);
			betting.setHandicapName("");
			betting.setBetRate(convertRate(drawList.get(i)));
			betting.setBetRateName("Draw");
			betting.setBetRateCode("X");
			game.addGameList(betting);

			// 패
			betting = new Game();
			betting.setBetTarget("Goals");
			betting.setBetTime("FT");
			betting.setBetType("1X2");
			betting.setBetName("Full Time Result");
			betting.setHandicap(0D);
			betting.setHandicapName("");
			betting.setBetRate(convertRate(awayList.get(i)));
			betting.setBetRateName(game.getAwayTeamCode());
			betting.setBetRateCode("2");
			game.addGameList(betting);

			game.setLink(linkList.get(i));

			// 나머지 베팅들
			this.getBettingList(game);

			// 게임설정 완료
			if (game.getGameList().size() > 0) {
				league.addGameList(game);
			}
		}
	}

	/**
	 * 추가 베팅
	 * 
	 * @param game
	 */
	private void getBettingList(Game game) {
		String source = httpService.getSource(convertLink(game.getLink()));

		Map<String, String> map = new HashMap<String, String>();
		map.put("betTarget", "Goals");
		map.put("betTime", "FT");

		// Double Chance
		map.put("betType", "DC");
		map.put("betName", "Double Chance");
		betDoubleChance(game, getBettingLink(source, "MA", "Double Chance"), map);

		// Total Goals
		map.put("betType", "OU");
		map.put("betName", "Total Goals");
		betOverUnder(game, getBettingLink(source, "MA", "Total Goals"), map);
		
		// Draw No Bet
		map.put("betType", "DNB");
		map.put("betName", "Draw No Bet");
		betHandicap(game, getBettingLink(source, "MA", "Draw No Bet"), map);

		// Asian Lines Link
		this.getAsianLines(game, getBettingLink(source, "PA", "Asian Lines"));

		// Cards Link
		this.getCards(game, getBettingLink(source, "PA", "Cards"));

		// Corners Link
		this.getCorners(game, getBettingLink(source, "PA", "Corners"));

		// Half Link
		this.getHalf(game, getBettingLink(source, "PA", "Half"));

	}

	/**
	 * Sub Menu Asian Lines
	 * 
	 * @param game
	 * @param link
	 */
	private void getAsianLines(Game game, String link) {
		if (link == null || "".equals(link))
			return;

		String source = httpService.getSource(convertLink(link));
		Map<String, String> map = new HashMap<String, String>();

		map.put("betTarget", "Goals");
		map.put("betTime", "FT");
		
		// Asian Handicap
		map.put("betType", "H");
		map.put("betName", "Asian Handicap");
		betHandicap(game, getBettingLink(source, "MA", "Asian Handicap"), map);

		// Goal Line
		map.put("betType", "OU");
		map.put("betName", "Goal Line");
		betOverUnder(game, getBettingLink(source, "MA", "Goal Line"), map);

		// Alternative Asian Handicap
		map.put("betType", "H");
		map.put("betName", "Alternative Asian Handicap");
		betHandicap(game, getBettingLink(source, "MA", "Alternative Asian Handicap"), map);

		// Alternative Goal Line
		map.put("betType", "OU");
		map.put("betName", "Alternative Goal Line");
		betOverUnder(game, getBettingLink(source, "MA", "Alternative Goal Line"), map);

		// 1st Half Asian Handicap
		map.put("betTime", "1H");
		
		map.put("betType", "H");
		map.put("betName", "1st Half Asian Handicap");
		betHandicap(game, getBettingLink(source, "MA", "1st Half Asian Handicap"), map);

		// 1st Half Goal Line
		map.put("betType", "OU");
		map.put("betName", "1st Half Goal Line");
		betOverUnder(game, getBettingLink(source, "MA", "1st Half Goal Line"), map);

		// Alternative 1st Half Asian Handicap
		map.put("betType", "H");
		map.put("betName", "Alternative 1st Half Asian Handicap");
		betHandicap(game, getBettingLink(source, "MA", "Alternative 1st Half Asian Handicap"), map);

		// Alternative 1st Half Goal Line
		map.put("betType", "OU");
		map.put("betName", "Alternative 1st Half Goal Line");
		betOverUnder(game, getBettingLink(source, "MA", "Alternative 1st Half Goal Line"), map);
	}

	/**
	 * Sub Menu Cards
	 * 
	 * @param game
	 * @param link
	 */
	private void getCards(Game game, String link) {
		if (link == null || "".equals(link))
			return;

		String source = httpService.getSource(convertLink(link));
		Map<String, String> map = new HashMap<String, String>();

		map.put("betTarget", "Cards");
		map.put("betTime", "FT");

		// Number of Cards in Match
		map.put("betType", "OU");
		map.put("betName", "Number of Cards in Match");
		betOverUnder(game, getBettingLink(source, "MA", "Number of Cards in Match"), map);

		// Card Handicap 1X2
		map.put("betType", "1X2");
		map.put("betName", "Card Handicap");
		betOverUnder(game, getBettingLink(source, "MA", "Card Handicap"), map);

		// Alternative Card Handicap
		map.put("betType", "H");
		map.put("betName", "Alternative Card Handicap");
		betOverUnder(game, getBettingLink(source, "MA", "Alternative Card Handicap"), map);

		// Asian Total Cards
		map.put("betName", "Asian Total Cards");
		betOverUnder(game, getBettingLink(source, "MA", "Asian Total Cards"), map);

		// Asian Handicap Cards
		map.put("betName", "Asian Handicap Cards");
		betHandicap(game, getBettingLink(source, "MA", "Asian Handicap Cards"), map);

	}

	/**
	 * Sub Menu Corners
	 * 
	 * @param game
	 * @param link
	 */
	private void getCorners(Game game, String link) {
		if (link == null || "".equals(link))
			return;

		String source = httpService.getSource(convertLink(link));
		Map<String, String> map = new HashMap<String, String>();

		map.put("betTarget", "Corners");
		map.put("betTime", "FT");

		// Corners
		map.put("betType", "OU");
		map.put("betName", "Corners");
		betOverUnder(game, getBettingLink(source, "MA", "Corners"), map);

		// Alternative Corners
		map.put("betName", "Alternative Corners");
		betOverUnder(game, getBettingLink(source, "MA", "Alternative Corners"), map);

		// Corners 2-Way
		map.put("betName", "Corners 2-Way");
		betOverUnder(game, getBettingLink(source, "MA", "Corners 2\\\\-Way"), map);

		// Corner Match Bet
		map.put("betType", "H");
		map.put("betName", "Corner Match Bet");
		betHandicap(game, getBettingLink(source, "MA", "Corner Match Bet"), map);

		// Corner Handicap
		map.put("betName", "Corner Handicap");
		betHandicap(game, getBettingLink(source, "MA", "Corner Handicap"), map);

		// Asian Handicap Corners
		map.put("betName", "Asian Handicap Corners");
		betHandicap(game, getBettingLink(source, "MA", "Asian Handicap Corners"), map);

		// Asian Total Corners
		map.put("betType", "OU");
		map.put("betName", "Asian Total Corners");
		betOverUnder(game, getBettingLink(source, "MA", "Asian Total Corners"), map);

		// First Half Corners
		map.put("betTime", "1H");
		map.put("betType", "H");
		map.put("betName", "First Half Corners");
		betOverUnder(game, getBettingLink(source, "MA", "First Half Corners"), map);

		// 1st Half Asian Corners
		map.put("betType", "OU");
		map.put("betName", "1st Half Asian Corners");
		betOverUnder(game, getBettingLink(source, "MA", "1st Half Asian Corners"), map);
	}

	/**
	 * Sub Menu Half
	 * 
	 * @param game
	 * @param link
	 */
	private void getHalf(Game game, String link) {
		if (link == null || "".equals(link))
			return;

		String source = httpService.getSource(convertLink(link));
		Map<String, String> map = new HashMap<String, String>();

		map.put("betTarget", "Goals");
		map.put("betTime", "1H");

		// Half-Time
		map.put("betName", "Half-Time");
		betHandicap(game, getBettingLink(source, "MA", "Half\\\\-Time"), map);

		// Half Time Double Chance
		map.put("betName", "Half Time Double Chance");
		betDoubleChance(game, getBettingLink(source, "MA", "Half Time Double Chance"), map);

		// Alternative 1st Half Handicap Result
		map.put("betName", "Alternative 1st Half Handicap Result");
		betHandicap(game, getBettingLink(source, "MA", "Alternative 1st Half Handicap Result"), map);

		// First Half Goals
		map.put("betName", "First Half Goals");
		betOverUnder(game, getBettingLink(source, "MA", "First Half Goals"), map);

		// 2nd Half Result
		map.put("betTime", "2H");
		map.put("betName", "2nd Half Result");
		betHandicap(game, getBettingLink(source, "MA", "2nd Half Result"), map);

		// 2nd Half Goals
		map.put("betName", "2nd Half Goals");
		betOverUnder(game, getBettingLink(source, "MA", "2nd Half Goals"), map);

	}
}
